import config from './config';
import reducers from './reducers';
import {IRedux} from "./redux";

const redux: IRedux = {
    /**
     * 监听
     * @param name  {string}    名称
     * @param callback  {function}  回调方法
     */
    listener<T>(name: string, callback: (params: T) => void): void {
        const lastDataMap = new WeakMap<Function, T | undefined>();
        reducers.subscribe(() => {
            if (typeof callback === 'function') {
                const result = redux.get<T>(name);
                const lastData = lastDataMap.get(callback);
                if (lastData === result) return;
                lastDataMap.set(callback, result);
                callback(result);
            }
        })
    },
    /**
     * 获取全部数据
     */
    all(): any {
        return reducers.getState()
    },
    /**
     * 根据名称获取数据
     * @param name  {string}    名称
     */
    get<T>(name: string): T {
        return redux.all()[name] as T
    },
    /**
     * 添加
     * @param name
     * @param params
     */
    add<T>(name: string, params: T): T {
        const data = redux.get<T>(name);
        if (typeof data === 'undefined') return redux.create(name, params);
        return redux.update<T>(name, params);
    },
    /**
     * 创建
     * @param name  {string}    名称
     * @param params
     * @param isInit    {boolean}   是否存储初始化值
     */
    create<T>(name: string, params: T, isInit?: boolean): T {
        reducers.dispatch(config.action.create(name, params, isInit));
        return redux.get<T>(name);
    },
    /**
     * 修改
     * @param name  {string}    名称
     * @param params
     */
    update<T>(name: string, params: T): T {
        reducers.dispatch(config.action.update(name, params));
        return redux.get<T>(name);
    },
    /**
     * 删除
     * @param name  {string}    名称
     */
    remove(name: string): void {
        reducers.dispatch(config.action.remove(name))
    },
    /**
     * 删除并重新初始化，必须在create()时，isInit = true 才可使用方法，否则报错
     * @param name  {string}    名称
     */
    removeAndInit(name: string): void {
        reducers.dispatch(config.action.removeAndInit(name))
    },
}

export default redux

